using System;
using System.Collections.Generic;
using System.Text;
using System.Runtime.InteropServices;
using System.Drawing;
using System.Drawing.Imaging;

using DirectShowLib;

namespace Pg.BioMedics.RatObserver.Media
{
    /// <summary>
    /// Sample grabber object
    /// </summary>
    internal sealed class SampleGrabberCB : ISampleGrabberCB
    {
        #region Fields

        private readonly BitmapType _BitmapType;
        private int _FrameWidth;
        private int _FrameHeight;
        private int _FrameStride;
        
        #endregion

        #region Constructors

        /// <summary>
        /// Initializes instance of SampleGrabberCB class for given image format
        /// </summary>
        /// <param name="videoWidth">frame bitmap width</param>
        /// <param name="videoHeight">frame bitmap heigth</param>
        /// <param name="type">image format</param>
        internal SampleGrabberCB(BitmapType type)
        {
            _BitmapType = type;
        }

        #endregion

        #region Properties

        /// <summary>
        /// Video frame width
        /// </summary>
        internal int FrameWidth
        {
            get
            {
                return _FrameWidth;
            }

            set
            {
                _FrameWidth = value;
            }
        }

        /// <summary>
        /// Video frame heigth
        /// </summary>
        internal int FrameHeight
        {
            get
            {
                return _FrameHeight;
            }

            set
            {
                _FrameHeight = value;
            }
        }

        /// <summary>
        /// Video frame stride
        /// </summary>
        internal int FrameStride
        {
            get
            {
                return _FrameStride;
            }

            set
            {
                _FrameStride = value;
            }
        }

        /// <summary>
        /// Bitmap type
        /// </summary>
        internal BitmapType BitmapType
        {
            get
            {
                return _BitmapType;
            }
        }

        #endregion

        #region ISampleGrabberCB Members

        public int BufferCB(double SampleTime, IntPtr pBuffer, int BufferLen)
        {
            if (OnFrameGrabbed != null)
            {
                // extract image
                PixelFormat pixelFormat = BitmapType == BitmapType.RGB24 ? PixelFormat.Format24bppRgb : PixelFormat.Format8bppIndexed;
                Bitmap frame = new Bitmap(FrameWidth, FrameHeight, FrameStride, pixelFormat, pBuffer);

                // notify about extraction
                return OnFrameGrabbed.Invoke(SampleTime, frame);
            }
            else
                return 0;
        }

        public int SampleCB(double SampleTime, IMediaSample pSample)
        {
            Marshal.ReleaseComObject(pSample);
            return 0;
        }

        #endregion

        #region Events

        internal event FrameGrabbedDelegate OnFrameGrabbed;

        #endregion
    }

    internal delegate int FrameGrabbedDelegate(double sampleTime, Bitmap bitmap);
}
